package com.school.sports.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.school.sports.dto.EnrollmentDTO;
import com.school.sports.entity.Enrollment;
import com.school.sports.entity.Project;
import com.school.sports.mapper.EnrollmentMapper;
import com.school.sports.service.EnrollmentService;
import com.school.sports.service.ProjectService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * 报名服务实现类
 * 实现了 EnrollmentService 接口中定义的所有业务方法
 * 包含优化的关联查询，解决N+1查询问题
 */
@Slf4j
@Service
public class EnrollmentServiceImpl extends ServiceImpl<EnrollmentMapper, Enrollment> implements EnrollmentService {

    @Autowired
    private ProjectService projectService;

    @Override
    public IPage<Enrollment> page(Page<Enrollment> page, LambdaQueryWrapper<Enrollment> queryWrapper) {
        return baseMapper.selectPage(page, queryWrapper);
    }

    @Override
    public IPage<EnrollmentDTO> pageEnrollmentsWithDetails(Page<EnrollmentDTO> page, Long userId, Long projectId, String status) {
        // 使用优化的JOIN查询，避免N+1问题
        return baseMapper.selectEnrollmentPageWithDetails(page, userId, projectId, status);
    }

    @Override
    public Enrollment getEnrollmentWithDetails(Long id) {
        // 暂时使用基础查询，后续可以添加关联查询
        return getById(id);
    }

    @Override
    public EnrollmentDTO getEnrollmentDetailsById(Long id) {
        // 使用优化的JOIN查询，避免N+1问题
        return baseMapper.selectEnrollmentByIdWithDetails(id);
    }

    @Override
    @Transactional
    public boolean enrollProject(Long userId, Long projectId, String healthStatement) {
        // 检查项目是否可以报名
        if (!canEnrollProject(projectId)) {
            log.warn("项目{}当前不可报名", projectId);
            return false;
        }

        // 检查用户是否已报名
        if (isUserEnrolled(userId, projectId)) {
            log.warn("用户{}已报名项目{}", userId, projectId);
            return false;
        }

        // 检查项目人数限制
        Project project = projectService.getById(projectId);
        if (project != null && project.getMaxPlayers() > 0) {
            long currentCount = countEnrollmentsByProjectId(projectId);
            if (currentCount >= project.getMaxPlayers()) {
                log.warn("项目{}报名人数已满", projectId);
                return false;
            }
        }

        // 创建报名记录
        Enrollment enrollment = new Enrollment();
        enrollment.setUserId(userId);
        enrollment.setProjectId(projectId);
        enrollment.setStatus("待审核");
        enrollment.setHealthStatement(healthStatement);
        enrollment.setCreatedAt(LocalDateTime.now());
        enrollment.setUpdatedAt(LocalDateTime.now());

        return save(enrollment);
    }

    @Override
    @Transactional
    public boolean cancelEnrollment(Long id, Long userId) {
        Enrollment enrollment = getById(id);
        if (enrollment == null || !enrollment.getUserId().equals(userId)) {
            return false;
        }

        if (!enrollment.canCancel()) {
            log.warn("报名记录{}当前状态不能取消", id);
            return false;
        }

        enrollment.setStatus("已取消");
        enrollment.setUpdatedAt(LocalDateTime.now());
        return updateById(enrollment);
    }

    @Override
    @Transactional
    public boolean auditEnrollment(Long id, String status, String rejectReason) {
        Enrollment enrollment = getById(id);
        if (enrollment == null) {
            return false;
        }

        if (!enrollment.canAudit()) {
            log.warn("报名记录{}当前状态不能审核", id);
            return false;
        }

        enrollment.setStatus(status);
        enrollment.setRejectReason("已驳回".equals(status) ? rejectReason : null);
        enrollment.setUpdatedAt(LocalDateTime.now());

        return updateById(enrollment);
    }

    @Override
    @Transactional
    public boolean batchAuditEnrollment(List<Long> ids, String status, String rejectReason) {
        try {
            for (Long id : ids) {
                auditEnrollment(id, status, rejectReason);
            }
            return true;
        } catch (Exception e) {
            log.error("批量审核报名失败：{}", e.getMessage(), e);
            return false;
        }
    }

    @Override
    public boolean isUserEnrolled(Long userId, Long projectId) {
        LambdaQueryWrapper<Enrollment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Enrollment::getUserId, userId)
                .eq(Enrollment::getProjectId, projectId)
                .ne(Enrollment::getStatus, "已取消");
        return count(queryWrapper) > 0;
    }

    @Override
    public List<Enrollment> getEnrollmentsByUserId(Long userId) {
        LambdaQueryWrapper<Enrollment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Enrollment::getUserId, userId)
                .orderByDesc(Enrollment::getCreatedAt);
        return list(queryWrapper);
    }

    @Override
    public List<EnrollmentDTO> getEnrollmentDetailsByUserId(Long userId) {
        // 使用优化的JOIN查询，避免N+1问题
        return baseMapper.selectEnrollmentsByUserIdWithDetails(userId);
    }

    @Override
    public List<Enrollment> getEnrollmentsByProjectId(Long projectId) {
        LambdaQueryWrapper<Enrollment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Enrollment::getProjectId, projectId)
                .orderByDesc(Enrollment::getCreatedAt);
        return list(queryWrapper);
    }

    @Override
    public List<EnrollmentDTO> getEnrollmentDetailsByProjectId(Long projectId) {
        // 使用优化的JOIN查询，避免N+1问题
        return baseMapper.selectEnrollmentsByProjectIdWithDetails(projectId);
    }

    @Override
    public List<Enrollment> getEnrollmentsByStatus(String status) {
        LambdaQueryWrapper<Enrollment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Enrollment::getStatus, status)
                .orderByDesc(Enrollment::getCreatedAt);
        return list(queryWrapper);
    }

    @Override
    public long countEnrollmentsByProjectId(Long projectId) {
        LambdaQueryWrapper<Enrollment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Enrollment::getProjectId, projectId)
                .ne(Enrollment::getStatus, "已取消");
        return count(queryWrapper);
    }

    @Override
    public long countEnrollmentsByStatus(String status) {
        LambdaQueryWrapper<Enrollment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Enrollment::getStatus, status);
        return count(queryWrapper);
    }

    @Override
    public List<String> getAllEnrollmentStatuses() {
        return Arrays.asList("待审核", "已通过", "已驳回", "已取消");
    }

    @Override
    public boolean canEnrollProject(Long projectId) {
        Project project = projectService.getById(projectId);
        if (project == null) {
            return false;
        }

        // 检查项目状态是否为"报名中"
        return "报名中".equals(project.getStatus());
    }

    @Override
    public Enrollment getByUserIdAndProjectId(Long userId, Long projectId) {
        LambdaQueryWrapper<Enrollment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Enrollment::getUserId, userId)
                .eq(Enrollment::getProjectId, projectId)
                .orderByDesc(Enrollment::getCreatedAt);
        queryWrapper.last("LIMIT 1");
        return getOne(queryWrapper);
    }
}